package chpt09;

import java.util.Random;


class Chopstick {
	private volatile int num;
	private volatile int count = 0; // 成功获取两只筷子的计数
	private volatile Object lock1 = new Object(); // chopstick1的锁
	private volatile Object lock2 = new Object(); // chopstick2的锁
	private volatile boolean chopstick1Flag = true; // 为true代表筷子还在
	private volatile boolean chopstick2Flag = true;
	private Random rnd = new Random(); // 可以使用ThreadLocalRandom改进

	public Chopstick(int num) {
		this.num = num;
	}

	/**
	 * 先拿筷子1,再拿筷子2
	 * 
	 * @return 两个筷子都拿到，返回true
	 */
	public boolean acquireChopstick1Firstly() {
		String name = Thread.currentThread().getName();
		System.out.println(name + " acquireChopstick1");
		synchronized (lock1) {
			if (chopstick1Flag == false) {
				return false;
			}
//			try {
//			Thread.sleep(rnd.nextInt(1)); //用于并发测试
//		} catch (InterruptedException e) {
//			e.printStackTrace();
//		}
			synchronized (lock2) {
				if (chopstick2Flag == false) {
					return false;
				}
			}
			chopstick1Flag = false;
			chopstick2Flag = false;
			return !chopstick1Flag && !chopstick2Flag;
		}
	}

	/**
	 * 先拿筷子2,再拿筷子1
	 * 
	 * @return 两个筷子都拿到，返回true
	 */
	public boolean acquireChopstick2Firstly() {
		String name = Thread.currentThread().getName();
		System.out.println(name + " acquireChopstick2");
		synchronized (lock2) {
			if (chopstick2Flag == false) {
				return false;
			}
//			try {
//			Thread.sleep(rnd.nextInt(1)); //用于并发测试
//		} catch (InterruptedException e) {
//			e.printStackTrace();
//		}
			synchronized (lock1) {
				if (chopstick1Flag == false) {
					return false;
				}
			}
			chopstick1Flag = false;
			chopstick2Flag = false;
			return !chopstick1Flag && !chopstick2Flag;
		}
	}

	public void acquireChopStickAndEat() {
		String name = Thread.currentThread().getName();
		boolean done = false;

		boolean flag = rnd.nextBoolean();
		if (flag) { // 随机选择一个方法
			done = acquireChopstick1Firstly();
		} else {
			done = acquireChopstick2Firstly();
		}

		if (done) { // 如果获得筷子
			//System.out.println(name + " 已获得两只筷子，可以用餐");
			count++;
			//System.out.println("name=" + name + " num=" + num);
		} else {
			System.out.println(name + "未获得筷子");
		}
		releaseChopstick1(); //释放筷子
		releaseChopstick2();
	}

	private void releaseChopstick1() {
		synchronized (lock1) {
			if (chopstick1Flag == false) {
				chopstick1Flag = true;
			}
		}
	}

	private void releaseChopstick2() {
		synchronized (lock2) {
			if (chopstick2Flag == false) {
				chopstick2Flag = true;
			}
		}
	}

	public synchronized int getNum() {
		return num;
	}

	public int getCount() {
		return count;
	}
	
	
}

public class ChopStickDeadLock {

	public static void main(String[] args) throws InterruptedException {
		int n = 1000000;
		Chopstick chopstick = new Chopstick(n);
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				for (int i = 0; i < n / 2; i++) {
					chopstick.acquireChopStickAndEat();
				}
			}
		});
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				for (int i = 0; i < n / 2; i++) {
					chopstick.acquireChopStickAndEat();
				}
			}
		});
		t1.start();
		t2.start();
		t1.join();
		t2.join();
		System.out.println("尝试获取的次数："+chopstick.getNum());
		System.out.println("成功获取的次数："+chopstick.getCount());
		System.out.println("main end");
	}

}
